﻿
// include files
#include <stdio.h>
#include <process.h>
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <errno.h>
#include "hexfile.h"
#include "user.h"

#define _GLOBAL_
  #include "global.h"
#undef _GLOBAL_

typedef struct{
    wchar_t filename[0xfff];
    MemoryImage_s* image;
}loadHexFile_params;
loadHexFile_params params;

unsigned int __stdcall loadHexFile_ThreadFunc(void* params)
{
    wchar_t filename_lower[0xfff];
    wcscpy(filename_lower, ((loadHexFile_params*)params)->filename);
    wcslwr(filename_lower);

    if(wcsstr(filename_lower, L".s19"))
    {
        import_file_s19(((loadHexFile_params*)params)->filename, ((loadHexFile_params*)params)->image);
    }
    else if(wcsstr(filename_lower, L".hex"))
    {
        import_file_ihx(((loadHexFile_params*)params)->filename, ((loadHexFile_params*)params)->image);
    }
    else if(wcsstr(filename_lower, L".bin"))
    {
        import_file_bin(((loadHexFile_params*)params)->filename, 0, ((loadHexFile_params*)params)->image);
    }
    else if (wcsstr(filename_lower, L".txt"))
    {
        import_file_txt(((loadHexFile_params*)params)->filename, ((loadHexFile_params*)params)->image);
    }

    return 0;
}

/// @brief 加载十六进制文件
/// @param[in]  filname   文件路径
/// @param[out]  hThread   文件加载线程句柄
/// @return 加载好的文件内存指针
handle_t CAPLEXPORT far CAPLPASCAL loadHexFile(wchar_t* filename, HANDLE* hThread)
{
    // HANDLE hLoadHexFile_Thread;

    uint32_t loadHexFile_ThreadID;
    // HANDLE* hLoadHexFile_Thread = (HANDLE*)malloc(sizeof(HANDLE));
    wcscpy(params.filename, filename);
    params.image = (MemoryImage_s*)malloc(sizeof(MemoryImage_s));
    MemoryImage_init(params.image);

    *hThread = (HANDLE)_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void *))loadHexFile_ThreadFunc, &params, 0, &loadHexFile_ThreadID);

    return params.image;
}

/// @brief 查看加载线程是否结束
/// @param[in]  filname   文件路径
/// @return 0:未结束 1:结束
DWORD CAPLEXPORT far CAPLPASCAL GetThreadSts(HANDLE hLoadHexFile_Thread)
{
    if(WAIT_OBJECT_0 == WaitForSingleObject(hLoadHexFile_Thread, 0))
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

/// @brief 释放十六进制文件
/// @param[in]  handle   内存指针
/// @return 0 表示成功，其他表示失败
handle_t CAPLEXPORT far CAPLPASCAL freeHexFile(handle_t h_File)
{
    MemoryImage_free((MemoryImage_s*)h_File);

    if(((MemoryImage_s*)h_File)->numEntries == 0)
    {
        free(h_File);
        return 0;
    }
    else
    {
        return h_File;
    }
}

/// @brief 获取首段落
/// @param[in]  h_File      加载文件的指针
/// @return 首段落内存指针
handle_t CAPLEXPORT far CAPLPASCAL getFirstSegment(handle_t h_File)
{
    MemoryImage_s* p = (MemoryImage_s*)h_File;

    if(p != NULL)
    {
        if(p->firstMemoryEntries != NULL)
        {
            return p->firstMemoryEntries;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return 0;
    }
}

/// @brief                获取当前段落
/// @param[in]  handle   段落指针
/// @param[io] addr      段落起始地址
/// @param[io] length    段落长度
/// @return   段落指针
handle_t CAPLEXPORT far CAPLPASCAL getThisSegment(handle_t h_Segment, DWORD* addr, DWORD* length)
{
    MemoryEntry_s* p = (MemoryEntry_s*)h_Segment;

    if(p != NULL)
    {
        *addr = p->addrStart;
        *length = p->capacityUsed;
        return h_Segment;
    }
    else
    {
        return 0;
    }
}

/// @brief 获取下一个段落
/// @param[in]  handle   内存指针
/// @param[io] addr      段落起始地址
/// @param[io] length    段落长度
/// @return   段落地址
handle_t CAPLEXPORT far CAPLPASCAL getNextSegment(handle_t h_Segment, DWORD* addr, DWORD* length)
{
    MemoryEntry_s* p = (MemoryEntry_s*)h_Segment;

    if(p != NULL)
    {
        if(p->next != NULL)
        {
            p = p->next;
            if(p != NULL)
            {
                *addr = p->addrStart;
                *length = p->capacityUsed;
                return p;
            }
            else
            {
                return 0;
            }
        }
    }
    else
    {
        return 0;
    }
}

/// @brief                获取当前段落数据
/// @param[in]  handle   内存指针
/// @param[out] data     输出数据
/// @param[in] size      想要获取数据的长度
/// @return   实际获取数据长度
DWORD CAPLEXPORT far CAPLPASCAL getThisSegmentData(handle_t h_Segment, uint8_t* data, DWORD size)
{
    MemoryEntry_s* p = (MemoryEntry_s*)h_Segment;

    if(p != NULL)
    {
        if(p->capacityUsed - p->alreadyRead > size)
        {
            memcpy(data,(p->data + p->alreadyRead),size);
            p->alreadyRead += size;
            return size;
        }
        else
        {
            memcpy(data,(p->data + p->alreadyRead),p->capacityUsed - p->alreadyRead);
            size = p->capacityUsed - p->alreadyRead;
            p->alreadyRead += (p->capacityUsed - p->alreadyRead);
            return size;
        }
        
    }
    else
    {
        return 0;
    }
}

// ============================================================================
// CAPL_DLL_INFO_LIST : 输出的函数列表
//   第一个字段是预定义的，不得更改！
//   第二个字段是预定义的，不得更改！
//   列表必须以{0,0}条目结束！
// 新结构支持最多50个字符的函数名称
// ============================================================================
CAPL_DLL_INFO4 table[] = {
{CDLL_VERSION_NAME, (CAPL_FARCALL)CDLL_VERSION, "", "", CAPL_DLL_CDECL, 0xabcd, CDLL_EXPORT },

  {"dllInit",           (CAPL_FARCALL)appInit,          "CAPL_DLL","This function will initialize all callback functions in the CAPLDLL",'V', 1, "D", "", {"handle"}},
  {"dllEnd",            (CAPL_FARCALL)appEnd,           "CAPL_DLL","This function will release the CAPL function handle in the CAPLDLL",'V', 1, "D", "", {"handle"}}, 
//从下面添加需要导出的函数，格式如下
//{导出函数名称,          函数地址,                       函数类别名称,   函数功能描述,           返回值数据类型,  函数参数数量,  参数的数据类型, 参数的维数(几维数组), 函数参数名称}
  {"loadHexFile",       (CAPL_FARCALL)loadHexFile,      "CAPL_DLL","Load .hex .s19 .bin .txt file, return (DWORD) memory handle",   'D',         2,          "BD",           {'\001','\001'},       {"FilePath_utf16_str","hLoadFileThread"}},
  {"freeHexFile",       (CAPL_FARCALL)freeHexFile,      "CAPL_DLL","Free .hex .s19 .bin .txt file, return (DWORD) 0:ok other:nok",  'D',         1,          "D",           {'\000'},               {"File_Handle"}},
  {"GetThreadSts",      (CAPL_FARCALL)GetThreadSts,     "CAPL_DLL","Get flile loading status,return (DWORD) 1:ok 0:nok",            'D',         1,          "D",           {'\000'},               {"hLoadFileThread"}},  
  {"getThisSegmentData",(CAPL_FARCALL)getThisSegmentData,"CAPL_DLL","Get segment data, return (DWORD) data length",                 'D',         3,          "DBD",         {'\000','\001','\000'}, {"Segment_Handle","Data_Byte_Array","Get_Data_Length"}},
  {"getFirstSegment",   (CAPL_FARCALL)getFirstSegment,   "CAPL_DLL","Get hex file first segment, return (DWORD) memory handle",     'D',         1,          "D",           {'\000'},               {"File_Handle"}},
  {"getThisSegment",    (CAPL_FARCALL)getThisSegment,   "CAPL_DLL","Get this segment, return (DWORD) this segment handle",          'D',         3,          "DDD",         {'\000','\001','\001'}, {"Segment_Handle","Segment_Addr","Segment_Length"}},
  {"getNextSegment",    (CAPL_FARCALL)getNextSegment,   "CAPL_DLL","Get next segment, return (DWORD) next segment handle",          'D',         3,          "DDD",         {'\000','\001','\001'}, {"Segment_Handle","Segment_Addr","Segment_Length"}},

//{导出函数名称,          函数地址,                       函数类别名称,   函数功能描述,           返回值数据类型,  函数参数数量,  参数的数据类型, 参数的维数(几维数组), 函数参数名称}
{0, 0}
};
CAPLEXPORT CAPL_DLL_INFO4 far * caplDllTable4 = table;
